"""
成绩分析窗口
Author: AI Assistant
Date: 2025-01-09
"""
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
from pathlib import Path
import os
from datetime import datetime
import sv_ttk

# 设置matplotlib中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False


class AnalysisWindow:
    def __init__(self, parent, output_dir, theme="light"):
        self.parent = parent
        self.output_dir = Path(output_dir)
        self.data = None
        self.current_theme = theme
        
        # 创建窗口
        self.window = tk.Toplevel(parent)
        self.window.title("📊 成绩分析报告")
        self.window.geometry("1000x700")
        self.window.minsize(800, 600)
        
        # 设置样式
        self.setup_styles()
        
        # 创建界面
        self.create_widgets()
        
        # 自动加载最新的Excel文件
        self.load_latest_excel()
        
    def setup_styles(self):
        """设置样式"""
        # 使用 Sun Valley 主题
        sv_ttk.set_theme(self.current_theme)
        
        style = ttk.Style()
        
        # 根据主题定义颜色方案
        if self.current_theme == "light":
            self.colors = {
                'primary': '#0078D4',      # 主色调 - 现代蓝
                'secondary': '#8764B8',    # 次要色 - 现代紫
                'success': '#107C10',      # 成功色 - 现代绿
                'background': '#FFFFFF',   # 背景色 - 白色
                'surface': '#F3F2F1',      # 表面色 - 浅灰
                'text': '#323130',         # 文字色 - 深灰
                'text_light': '#605E5C',   # 浅文字色 - 中灰
                'accent': '#0078D4'        # 强调色 - 现代蓝
            }
        else:  # dark theme
            self.colors = {
                'primary': '#60CDFF',      # 主色调 - 亮蓝
                'secondary': '#B4A7D6',    # 次要色 - 亮紫
                'success': '#6FBD44',      # 成功色 - 亮绿
                'background': '#1E1E1E',   # 背景色 - 深色
                'surface': '#2D2D30',      # 表面色 - 深灰
                'text': '#FFFFFF',         # 文字色 - 白色
                'text_light': '#CCCCCC',   # 浅文字色 - 浅灰
                'accent': '#60CDFF'        # 强调色 - 亮蓝
            }
        
        # 配置窗口背景
        self.window.configure(bg=self.colors['background'])
        
        # 配置Title.TFrame样式 - 使用浅灰色背景
        style.configure('Title.TFrame',
                       background=self.colors['background'])
        
    def create_widgets(self):
        """创建界面组件"""
        # 主框架
        main_frame = ttk.Frame(self.window, padding="20")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(1, weight=1)
        
        # 标题和控制面板
        self.create_header(main_frame, 0)
        
        # 内容区域
        self.create_content(main_frame, 1)
        
    def create_header(self, parent, row):
        """创建标题和控制面板"""
        header_frame = ttk.Frame(parent)
        header_frame.grid(row=row, column=0, sticky=(tk.W, tk.E), pady=(0, 20))
        header_frame.columnconfigure(1, weight=1)
        
        # 标题
        title_label = ttk.Label(header_frame, text="📊 成绩分析报告", 
                               font=('Microsoft YaHei', 16, 'bold'),
                               foreground=self.colors['primary'])
        title_label.grid(row=0, column=0, sticky=tk.W, padx=(0, 20))
        
        # 控制按钮
        button_frame = ttk.Frame(header_frame)
        button_frame.grid(row=0, column=1, sticky=tk.E)
        
        ttk.Button(button_frame, text="📁 选择文件", command=self.select_excel_file,
                  style='Secondary.TButton').grid(row=0, column=0, padx=(0, 10))
        ttk.Button(button_frame, text="🔄 刷新数据", command=self.refresh_data,
                  style='Secondary.TButton').grid(row=0, column=1, padx=(0, 10))
        ttk.Button(button_frame, text="💾 导出报告", command=self.export_report,
                  style='Secondary.TButton').grid(row=0, column=2)
        
    def create_content(self, parent, row):
        """创建内容区域"""
        # 创建Notebook用于标签页
        self.notebook = ttk.Notebook(parent)
        self.notebook.grid(row=row, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 统计信息标签页
        self.create_stats_tab()
        
        # 图表分析标签页
        self.create_charts_tab()
        
        # 详细数据标签页
        self.create_data_tab()
        
    def create_stats_tab(self):
        """创建统计信息标签页"""
        stats_frame = ttk.Frame(self.notebook)
        self.notebook.add(stats_frame, text="📈 统计信息")
        
        # 创建滚动区域
        canvas = tk.Canvas(stats_frame, bg=self.colors['background'])
        scrollbar = ttk.Scrollbar(stats_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        
        # 让内容在canvas中居中
        def configure_scroll_region(event):
            canvas.configure(scrollregion=canvas.bbox("all"))
            # 居中显示内容
            canvas_width = event.width
            frame_width = scrollable_frame.winfo_reqwidth()
            if frame_width < canvas_width:
                canvas.coords(scrollable_frame, canvas_width // 2, 0)
        
        scrollable_frame.bind("<Configure>", configure_scroll_region)
        canvas.configure(yscrollcommand=scrollbar.set)
        
        # 创建统计信息容器
        self.stats_container = ttk.Frame(scrollable_frame)
        self.stats_container.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=20, pady=20)
        self.stats_container.columnconfigure(0, weight=1)
        self.stats_container.rowconfigure(1, weight=1)
        
        # 布局
        canvas.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        stats_frame.columnconfigure(0, weight=1)
        stats_frame.rowconfigure(0, weight=1)
        
        # 初始化统计信息显示
        self.create_stats_display()
        
        # 更新canvas滚动区域
        self.update_canvas_scroll()
        
    def update_canvas_scroll(self):
        """更新canvas滚动区域"""
        try:
            # 更新滚动区域
            if hasattr(self, 'stats_frame'):
                self.stats_frame.update_idletasks()
                bbox = self.stats_frame.bbox("all")
                if bbox:
                    self.stats_frame.configure(scrollregion=bbox)
        except:
            pass
        
    def create_stats_display(self):
        """创建美观的统计信息显示"""
        # 清除现有内容
        for widget in self.stats_container.winfo_children():
            widget.destroy()
            
        # 存储stats_frame引用
        self.stats_frame = self.stats_container
        
        # 标题
        title_frame = ttk.Frame(self.stats_container)
        title_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 20))
        title_frame.columnconfigure(0, weight=1)
        
        title_label = ttk.Label(title_frame, text="📊 成绩统计报告", 
                               font=('Microsoft YaHei', 18, 'bold'),
                               foreground=self.colors['primary'])
        title_label.grid(row=0, column=0, pady=(0, 10))
        
        # 创建统计卡片容器
        self.stats_cards = ttk.Frame(self.stats_container)
        self.stats_cards.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        self.stats_cards.columnconfigure(0, weight=1)
        self.stats_cards.columnconfigure(1, weight=1)
        self.stats_cards.columnconfigure(2, weight=1)
        self.stats_cards.columnconfigure(3, weight=1)
        self.stats_cards.rowconfigure(0, weight=1)
        self.stats_cards.rowconfigure(1, weight=1)
        
        # 初始化卡片
        self.create_stat_cards()
        
    def create_stat_cards(self):
        """创建统计卡片"""
        # 基本统计卡片
        self.create_basic_stats_card(0, 0)
        self.create_grade_distribution_card(0, 1)
        self.create_score_range_card(0, 2)
        self.create_performance_card(0, 3)
        
        # 详细分析卡片
        self.create_detailed_analysis_card(1, 0, columnspan=4)
        
    def create_basic_stats_card(self, row, column):
        """创建基本统计卡片"""
        card_frame = ttk.LabelFrame(self.stats_cards, text="📈 基本统计", 
                                   style='Custom.TLabelframe', padding="15")
        card_frame.grid(row=row, column=column, sticky=(tk.W, tk.E, tk.N, tk.S), 
                       padx=(0, 10), pady=(0, 10))
        card_frame.columnconfigure(0, weight=1)
        
        # 统计项目
        stats_items = [
            ("总学生数", "0", "人"),
            ("平均分", "0.0", "分"),
            ("最高分", "0", "分"),
            ("最低分", "0", "分"),
            ("标准差", "0.0", "")
        ]
        
        for i, (label, value, unit) in enumerate(stats_items):
            item_frame = ttk.Frame(card_frame)
            item_frame.grid(row=i, column=0, sticky=(tk.W, tk.E), pady=2)
            item_frame.columnconfigure(1, weight=1)
            
            ttk.Label(item_frame, text=label, font=('Microsoft YaHei', 10)).grid(row=0, column=0, sticky=tk.W)
            value_label = ttk.Label(item_frame, text=f"{value}{unit}", 
                                   font=('Microsoft YaHei', 12, 'bold'),
                                   foreground=self.colors['primary'])
            value_label.grid(row=0, column=1, sticky=tk.E)
            
            # 存储引用以便更新
            setattr(self, f"basic_{label.replace('数', '').replace('分', '').replace('标准差', 'std')}_label", value_label)
    
    def create_grade_distribution_card(self, row, column):
        """创建等级分布卡片"""
        card_frame = ttk.LabelFrame(self.stats_cards, text="🎯 等级分布", 
                                   style='Custom.TLabelframe', padding="15")
        card_frame.grid(row=row, column=column, sticky=(tk.W, tk.E, tk.N, tk.S), 
                       padx=(0, 10), pady=(0, 10))
        card_frame.columnconfigure(0, weight=1)
        
        # 等级项目
        grade_items = [
            ("优秀", "90-100", "0", "0%"),
            ("良好", "80-89", "0", "0%"),
            ("中等", "70-79", "0", "0%"),
            ("及格", "60-69", "0", "0%"),
            ("不及格", "<60", "0", "0%")
        ]
        
        for i, (grade, range_text, count, percentage) in enumerate(grade_items):
            item_frame = ttk.Frame(card_frame)
            item_frame.grid(row=i, column=0, sticky=(tk.W, tk.E), pady=2)
            item_frame.columnconfigure(1, weight=1)
            
            # 等级名称和范围
            grade_label = ttk.Label(item_frame, text=f"{grade} ({range_text})", 
                                   font=('Microsoft YaHei', 10))
            grade_label.grid(row=0, column=0, sticky=tk.W)
            
            # 数量和百分比
            count_label = ttk.Label(item_frame, text=f"{count}人 ({percentage})", 
                                   font=('Microsoft YaHei', 10, 'bold'),
                                   foreground=self.colors['secondary'])
            count_label.grid(row=0, column=1, sticky=tk.E)
            
            # 存储引用以便更新
            setattr(self, f"grade_{grade}_label", count_label)
    
    def create_score_range_card(self, row, column):
        """创建分数区间卡片"""
        card_frame = ttk.LabelFrame(self.stats_cards, text="📊 分数区间", 
                                   style='Custom.TLabelframe', padding="15")
        card_frame.grid(row=row, column=column, sticky=(tk.W, tk.E, tk.N, tk.S), 
                       padx=(0, 10), pady=(0, 10))
        card_frame.columnconfigure(0, weight=1)
        
        # 分数区间
        range_items = [
            ("90-100", "0", "0%"),
            ("80-89", "0", "0%"),
            ("70-79", "0", "0%"),
            ("60-69", "0", "0%"),
            ("0-59", "0", "0%")
        ]
        
        for i, (range_text, count, percentage) in enumerate(range_items):
            item_frame = ttk.Frame(card_frame)
            item_frame.grid(row=i, column=0, sticky=(tk.W, tk.E), pady=2)
            item_frame.columnconfigure(1, weight=1)
            
            ttk.Label(item_frame, text=f"{range_text}分", 
                     font=('Microsoft YaHei', 10)).grid(row=0, column=0, sticky=tk.W)
            count_label = ttk.Label(item_frame, text=f"{count}人 ({percentage})", 
                                   font=('Microsoft YaHei', 10, 'bold'),
                                   foreground=self.colors['success'])
            count_label.grid(row=0, column=1, sticky=tk.E)
            
            # 存储引用以便更新
            setattr(self, f"range_{range_text.replace('-', '_')}_label", count_label)
    
    def create_performance_card(self, row, column):
        """创建表现分析卡片"""
        card_frame = ttk.LabelFrame(self.stats_cards, text="⭐ 表现分析", 
                                   style='Custom.TLabelframe', padding="15")
        card_frame.grid(row=row, column=column, sticky=(tk.W, tk.E, tk.N, tk.S), 
                       padx=(0, 10), pady=(0, 10))
        card_frame.columnconfigure(0, weight=1)
        
        # 表现指标
        performance_items = [
            ("及格率", "0%"),
            ("优秀率", "0%"),
            ("平均等级", "无"),
            ("成绩稳定性", "无"),
            ("整体评价", "无数据")
        ]
        
        for i, (metric, value) in enumerate(performance_items):
            item_frame = ttk.Frame(card_frame)
            item_frame.grid(row=i, column=0, sticky=(tk.W, tk.E), pady=2)
            item_frame.columnconfigure(1, weight=1)
            
            ttk.Label(item_frame, text=metric, 
                     font=('Microsoft YaHei', 10)).grid(row=0, column=0, sticky=tk.W)
            value_label = ttk.Label(item_frame, text=value, 
                                   font=('Microsoft YaHei', 10, 'bold'),
                                   foreground=self.colors['accent'])
            value_label.grid(row=0, column=1, sticky=tk.E)
            
            # 存储引用以便更新
            setattr(self, f"perf_{metric}_label", value_label)
    
    def create_detailed_analysis_card(self, row, column, columnspan=1):
        """创建详细分析卡片"""
        card_frame = ttk.LabelFrame(self.stats_cards, text="📋 详细分析", 
                                   style='Custom.TLabelframe', padding="15")
        card_frame.grid(row=row, column=column, columnspan=columnspan, sticky=(tk.W, tk.E, tk.N, tk.S), 
                       pady=(10, 0))
        card_frame.columnconfigure(0, weight=1)
        card_frame.rowconfigure(0, weight=1)
        
        # 分析文本
        self.analysis_text = tk.Text(card_frame, height=8, width=80, 
                                    font=('Microsoft YaHei', 10),
                                    wrap=tk.WORD, bg=self.colors['surface'],
                                    fg=self.colors['text'], relief='solid', borderwidth=1)
        self.analysis_text.grid(row=0, column=0, sticky=(tk.W, tk.E))
        
        # 添加滚动条
        analysis_scrollbar = ttk.Scrollbar(card_frame, orient="vertical", command=self.analysis_text.yview)
        self.analysis_text.configure(yscrollcommand=analysis_scrollbar.set)
        analysis_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
    def create_charts_tab(self):
        """创建图表分析标签页"""
        charts_frame = ttk.Frame(self.notebook)
        self.notebook.add(charts_frame, text="📊 图表分析")
        
        # 创建matplotlib图形
        self.fig = Figure(figsize=(12, 8), dpi=100, facecolor=self.colors['background'])
        self.canvas = FigureCanvasTkAgg(self.fig, charts_frame)
        self.canvas.get_tk_widget().grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        charts_frame.columnconfigure(0, weight=1)
        charts_frame.rowconfigure(0, weight=1)
        
    def create_data_tab(self):
        """创建详细数据标签页"""
        data_frame = ttk.Frame(self.notebook)
        self.notebook.add(data_frame, text="📋 详细数据")
        
        # 创建Treeview显示数据
        columns = ('学号', '姓名', '成绩', '评语', '评分时间')
        self.tree = ttk.Treeview(data_frame, columns=columns, show='headings', height=20)
        
        # 设置列标题
        for col in columns:
            self.tree.heading(col, text=col)
            self.tree.column(col, width=120, anchor='center')
        
        # 添加滚动条
        tree_scrollbar = ttk.Scrollbar(data_frame, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=tree_scrollbar.set)
        
        # 布局
        self.tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        tree_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        data_frame.columnconfigure(0, weight=1)
        data_frame.rowconfigure(0, weight=1)
        
    def load_latest_excel(self):
        """加载最新的Excel文件"""
        try:
            # 查找Excel文件
            excel_files = list(self.output_dir.glob("评分结果_*.xlsx"))
            if excel_files:
                # 使用最新的文件
                latest_file = max(excel_files, key=lambda x: x.stat().st_mtime)
                self.load_excel_file(latest_file)
            else:
                self.show_message("未找到评分结果文件")
        except Exception as e:
            self.show_message(f"加载文件失败: {str(e)}")
            
    def select_excel_file(self):
        """选择Excel文件"""
        file_path = filedialog.askopenfilename(
            title="选择评分结果文件",
            filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")]
        )
        if file_path:
            self.load_excel_file(Path(file_path))
            
    def load_excel_file(self, file_path):
        """加载Excel文件"""
        try:
            self.data = pd.read_excel(file_path)
            self.current_file = file_path
            self.refresh_data()
            self.show_message(f"已加载文件: {file_path.name}")
        except Exception as e:
            self.show_message(f"加载文件失败: {str(e)}")
            
    def refresh_data(self):
        """刷新数据"""
        if self.data is None:
            self.show_message("请先选择数据文件")
            return
            
        try:
            # 更新统计信息
            self.update_stats()
            
            # 更新图表
            self.update_charts()
            
            # 更新详细数据
            self.update_data_table()
            
        except Exception as e:
            self.show_message(f"刷新数据失败: {str(e)}")
            
    def update_stats(self):
        """更新统计信息"""
        if self.data is None:
            return
            
        # 计算统计信息
        scores = self.data['成绩'].tolist()
        total_students = len(scores)
        avg_score = np.mean(scores)
        max_score = np.max(scores)
        min_score = np.min(scores)
        std_score = np.std(scores)
        
        # 更新基本统计卡片
        self.update_basic_stats(total_students, avg_score, max_score, min_score, std_score)
        
        # 更新等级分布卡片
        self.update_grade_distribution(scores, total_students)
        
        # 更新分数区间卡片
        self.update_score_ranges(scores, total_students)
        
        # 更新表现分析卡片
        self.update_performance_analysis(scores, total_students, avg_score, std_score)
        
        # 更新详细分析
        self.update_detailed_analysis(scores, total_students, avg_score, max_score, min_score, std_score)
        
        # 更新canvas滚动区域
        self.update_canvas_scroll()
        
    def update_basic_stats(self, total_students, avg_score, max_score, min_score, std_score):
        """更新基本统计"""
        if hasattr(self, 'basic_总学生_label'):
            self.basic_总学生_label.config(text=f"{total_students}人")
        if hasattr(self, 'basic_平均_label'):
            self.basic_平均_label.config(text=f"{avg_score:.2f}分")
        if hasattr(self, 'basic_最高_label'):
            self.basic_最高_label.config(text=f"{max_score}分")
        if hasattr(self, 'basic_最低_label'):
            self.basic_最低_label.config(text=f"{min_score}分")
        if hasattr(self, 'basic_std_label'):
            self.basic_std_label.config(text=f"{std_score:.2f}")
    
    def update_grade_distribution(self, scores, total_students):
        """更新等级分布"""
        excellent = len([s for s in scores if s >= 90])
        good = len([s for s in scores if 80 <= s < 90])
        medium = len([s for s in scores if 70 <= s < 80])
        pass_grade = len([s for s in scores if 60 <= s < 70])
        fail = len([s for s in scores if s < 60])
        
        grade_data = [
            ("优秀", excellent, (excellent/total_students)*100),
            ("良好", good, (good/total_students)*100),
            ("中等", medium, (medium/total_students)*100),
            ("及格", pass_grade, (pass_grade/total_students)*100),
            ("不及格", fail, (fail/total_students)*100)
        ]
        
        for grade, count, percentage in grade_data:
            label_name = f'grade_{grade}_label'
            if hasattr(self, label_name):
                getattr(self, label_name).config(text=f"{count}人 ({percentage:.1f}%)")
    
    def update_score_ranges(self, scores, total_students):
        """更新分数区间"""
        ranges = [
            ("90_100", 90, 100),
            ("80_89", 80, 89),
            ("70_79", 70, 79),
            ("60_69", 60, 69),
            ("0_59", 0, 59)
        ]
        
        for range_name, min_val, max_val in ranges:
            if range_name == "0_59":
                count = len([s for s in scores if s < 60])
            else:
                count = len([s for s in scores if min_val <= s <= max_val])
            percentage = (count / total_students) * 100
            
            label_name = f'range_{range_name}_label'
            if hasattr(self, label_name):
                getattr(self, label_name).config(text=f"{count}人 ({percentage:.1f}%)")
    
    def update_performance_analysis(self, scores, total_students, avg_score, std_score):
        """更新表现分析"""
        # 及格率
        pass_count = len([s for s in scores if s >= 60])
        pass_rate = (pass_count / total_students) * 100
        
        # 优秀率
        excellent_count = len([s for s in scores if s >= 90])
        excellent_rate = (excellent_count / total_students) * 100
        
        # 平均等级
        if avg_score >= 90:
            avg_grade = "优秀"
        elif avg_score >= 80:
            avg_grade = "良好"
        elif avg_score >= 70:
            avg_grade = "中等"
        elif avg_score >= 60:
            avg_grade = "及格"
        else:
            avg_grade = "不及格"
        
        # 成绩稳定性
        if std_score <= 10:
            stability = "很稳定"
        elif std_score <= 15:
            stability = "较稳定"
        elif std_score <= 20:
            stability = "一般"
        else:
            stability = "不稳定"
        
        # 整体评价
        if avg_score >= 85 and pass_rate >= 90:
            overall = "优秀"
        elif avg_score >= 75 and pass_rate >= 80:
            overall = "良好"
        elif avg_score >= 65 and pass_rate >= 70:
            overall = "中等"
        else:
            overall = "需要改进"
        
        # 更新标签
        if hasattr(self, 'perf_及格率_label'):
            self.perf_及格率_label.config(text=f"{pass_rate:.1f}%")
        if hasattr(self, 'perf_优秀率_label'):
            self.perf_优秀率_label.config(text=f"{excellent_rate:.1f}%")
        if hasattr(self, 'perf_平均等级_label'):
            self.perf_平均等级_label.config(text=avg_grade)
        if hasattr(self, 'perf_成绩稳定性_label'):
            self.perf_成绩稳定性_label.config(text=stability)
        if hasattr(self, 'perf_整体评价_label'):
            self.perf_整体评价_label.config(text=overall)
    
    def update_detailed_analysis(self, scores, total_students, avg_score, max_score, min_score, std_score):
        """更新详细分析"""
        analysis_text = f"""
📊 成绩分析报告
生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

📈 数据概览
本次分析共包含 {total_students} 名学生的成绩数据。平均分为 {avg_score:.2f} 分，
最高分为 {max_score} 分，最低分为 {min_score} 分，标准差为 {std_score:.2f}。

🎯 成绩分布特点
"""
        
        # 分析成绩分布
        excellent = len([s for s in scores if s >= 90])
        good = len([s for s in scores if 80 <= s < 90])
        medium = len([s for s in scores if 70 <= s < 80])
        pass_grade = len([s for s in scores if 60 <= s < 70])
        fail = len([s for s in scores if s < 60])
        
        analysis_text += f"• 优秀学生（90分以上）: {excellent}人，占比 {(excellent/total_students)*100:.1f}%\n"
        analysis_text += f"• 良好学生（80-89分）: {good}人，占比 {(good/total_students)*100:.1f}%\n"
        analysis_text += f"• 中等学生（70-79分）: {medium}人，占比 {(medium/total_students)*100:.1f}%\n"
        analysis_text += f"• 及格学生（60-69分）: {pass_grade}人，占比 {(pass_grade/total_students)*100:.1f}%\n"
        analysis_text += f"• 不及格学生（60分以下）: {fail}人，占比 {(fail/total_students)*100:.1f}%\n\n"
        
        # 分析成绩特点
        pass_rate = ((total_students - fail) / total_students) * 100
        analysis_text += f"📊 整体表现\n"
        analysis_text += f"• 及格率: {pass_rate:.1f}%\n"
        analysis_text += f"• 优秀率: {(excellent/total_students)*100:.1f}%\n"
        
        if std_score <= 10:
            analysis_text += f"• 成绩分布较为集中，标准差为 {std_score:.2f}，说明学生水平相对均衡\n"
        elif std_score <= 20:
            analysis_text += f"• 成绩分布适中，标准差为 {std_score:.2f}，存在一定的个体差异\n"
        else:
            analysis_text += f"• 成绩分布较为分散，标准差为 {std_score:.2f}，学生水平差异较大\n"
        
        # 给出建议
        analysis_text += f"\n💡 教学建议\n"
        if avg_score >= 85:
            analysis_text += "• 整体成绩优秀，建议继续保持当前教学方式\n"
        elif avg_score >= 75:
            analysis_text += "• 整体成绩良好，可以适当增加挑战性内容\n"
        elif avg_score >= 65:
            analysis_text += "• 整体成绩中等，建议加强基础知识的巩固\n"
        else:
            analysis_text += "• 整体成绩偏低，建议重新审视教学方法和内容\n"
        
        if fail > total_students * 0.2:
            analysis_text += "• 不及格率较高，建议重点关注学习困难学生\n"
        
        if excellent < total_students * 0.1:
            analysis_text += "• 优秀学生较少，可以增加拔高性内容\n"
        
        # 更新分析文本
        if hasattr(self, 'analysis_text'):
            self.analysis_text.delete('1.0', tk.END)
            self.analysis_text.insert('1.0', analysis_text)
        
    def update_charts(self):
        """更新图表"""
        if self.data is None:
            return
            
        # 清除之前的图表
        self.fig.clear()
        
        scores = self.data['成绩'].tolist()
        
        # 创建2x2的子图布局
        ax1 = self.fig.add_subplot(2, 2, 1)
        ax2 = self.fig.add_subplot(2, 2, 2)
        ax3 = self.fig.add_subplot(2, 2, 3)
        ax4 = self.fig.add_subplot(2, 2, 4)
        
        # 1. 分数分布直方图
        ax1.hist(scores, bins=10, color=self.colors['primary'], alpha=0.7, edgecolor='black')
        ax1.set_title('分数分布直方图', fontsize=12, fontweight='bold')
        ax1.set_xlabel('分数')
        ax1.set_ylabel('人数')
        ax1.grid(True, alpha=0.3)
        
        # 2. 分数折线图
        student_indices = range(1, len(scores) + 1)
        ax2.plot(student_indices, scores, marker='o', color=self.colors['secondary'], linewidth=2, markersize=4)
        ax2.set_title('分数折线图', fontsize=12, fontweight='bold')
        ax2.set_xlabel('学生序号')
        ax2.set_ylabel('分数')
        ax2.grid(True, alpha=0.3)
        ax2.set_ylim(0, 100)
        
        # 3. 等级分布饼图
        excellent = len([s for s in scores if s >= 90])
        good = len([s for s in scores if 80 <= s < 90])
        medium = len([s for s in scores if 70 <= s < 80])
        pass_grade = len([s for s in scores if 60 <= s < 70])
        fail = len([s for s in scores if s < 60])
        
        labels = ['优秀', '良好', '中等', '及格', '不及格']
        sizes = [excellent, good, medium, pass_grade, fail]
        colors = ['#28a745', '#17a2b8', '#ffc107', '#fd7e14', '#dc3545']
        
        # 过滤掉0值
        filtered_data = [(label, size, color) for label, size, color in zip(labels, sizes, colors) if size > 0]
        if filtered_data:
            labels, sizes, colors = zip(*filtered_data)
            ax3.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
        ax3.set_title('等级分布饼图', fontsize=12, fontweight='bold')
        
        # 4. 箱线图
        ax4.boxplot(scores, patch_artist=True, 
                   boxprops=dict(facecolor=self.colors['success'], alpha=0.7),
                   medianprops=dict(color='red', linewidth=2))
        ax4.set_title('分数箱线图', fontsize=12, fontweight='bold')
        ax4.set_ylabel('分数')
        ax4.grid(True, alpha=0.3)
        
        # 调整布局
        self.fig.tight_layout()
        self.canvas.draw()
        
    def update_data_table(self):
        """更新数据表格"""
        if self.data is None:
            return
            
        # 清除现有数据
        for item in self.tree.get_children():
            self.tree.delete(item)
            
        # 添加数据
        for index, row in self.data.iterrows():
            self.tree.insert('', 'end', values=(
                row['学号'],
                row['姓名'],
                row['成绩'],
                row['评语'][:50] + '...' if len(str(row['评语'])) > 50 else row['评语'],
                row['评分时间']
            ))
            
    def export_report(self):
        """导出报告"""
        if self.data is None:
            self.show_message("请先加载数据")
            return
            
        try:
            # 选择保存路径
            file_path = filedialog.asksaveasfilename(
                title="保存分析报告",
                defaultextension=".txt",
                filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
            )
            
            if file_path:
                # 生成报告内容
                report_content = self.generate_report_content()
                
                # 保存文件
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(report_content)
                    
                self.show_message(f"报告已保存到: {file_path}")
                
        except Exception as e:
            self.show_message(f"导出报告失败: {str(e)}")
            
    def generate_report_content(self):
        """生成报告内容"""
        scores = self.data['成绩'].tolist()
        total_students = len(scores)
        avg_score = np.mean(scores)
        max_score = np.max(scores)
        min_score = np.min(scores)
        std_score = np.std(scores)
        
        report = f"""
成绩分析报告
{'='*50}

生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
数据文件: {self.current_file.name}

基本统计信息
• 总学生数: {total_students} 人
• 平均分: {avg_score:.2f} 分
• 最高分: {max_score} 分
• 最低分: {min_score} 分
• 标准差: {std_score:.2f}

等级分布
• 优秀 (90-100分): {len([s for s in scores if s >= 90])}人
• 良好 (80-89分): {len([s for s in scores if 80 <= s < 90])}人
• 中等 (70-79分): {len([s for s in scores if 70 <= s < 79])}人
• 及格 (60-69分): {len([s for s in scores if 60 <= s < 70])}人
• 不及格 (<60分): {len([s for s in scores if s < 60])}人

详细数据
{'学号':<15} {'姓名':<10} {'成绩':<8} {'评语':<30}
{'-'*70}
"""
        
        for _, row in self.data.iterrows():
            report += f"{row['学号']:<15} {row['姓名']:<10} {row['成绩']:<8} {str(row['评语'])[:30]:<30}\n"
            
        return report
        
    def show_message(self, message):
        """显示消息"""
        messagebox.showinfo("提示", message)


def open_analysis_window(parent, output_dir, theme="light"):
    """打开分析窗口"""
    AnalysisWindow(parent, output_dir, theme)
